package com.iflytek.edu.db.ext.mybatis;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.druid.DbType;
import com.iflytek.edu.db.core.parse.SqlAdapter;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.sql.Connection;

/**
 * mybatis适配器
 * </p>拦截StatementHandler类中参数类型为Statement的 prepare 方法
 * </p>即拦截 Statement prepare(Connection var1, Integer var2) 方法
 *
 * @author linkai
 * @date 2022/2/11
 */
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MybatisInterceptorAdapter implements Interceptor {

    private final SqlAdapter sqlParse;
    private final static String SQL_FIELD = "sql";

    public MybatisInterceptorAdapter(SqlAdapter sqlParse) {
        this.sqlParse = SqlAdapter.create(DbType.dm);
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        // 获取到原始sql语句
        String sql = boundSql.getSql();
        log.info("druid adapter before! \nsql = {}", sql);
        // 适配SQL
        sql = sqlParse.parse(sql);
        log.info("druid adapter after! \nsql = {}", sql);
        // 通过反射修改sql语句
        ReflectUtil.setFieldValue(boundSql, SQL_FIELD, sql);
        return invocation.proceed();
    }
}
